﻿using System;
using System.Xml;
using System.Collections.Generic;

namespace Douya.Json
{
    public class XmlParser
    {
        HashSet<String> set = new HashSet<string>();

        public JsonObject Parse(string xml, params Object[] args)
        {
            foreach (string arg in args)
            {
                set.Add(arg);
            }

            ObjectBuilder builder = new ObjectBuilder();

            if (!string.IsNullOrEmpty(xml) && xml.StartsWith("<"))
            {
                XmlDocument dom = new XmlDocument();
                dom.LoadXml(xml);
                ParseObject(builder, dom.DocumentElement);
            }

            return builder.Build();
        }

        ObjectBuilder ParseObject(ObjectBuilder builder, XmlNode parent)
        {
            for (int i = 0; i < parent.ChildNodes.Count; ++i)
            {
                XmlNode node = parent.ChildNodes[i];
                if (node.NodeType == XmlNodeType.Text)
                {
                    //
                }
                else if (HasChild(node))
                {
                    if (set.Contains(node.Name) || IsArray(node))
                    {
                        i += ParseArray(builder, node);
                        --i;
                    }
                    else
                    {
                        builder.Add(node.Name, ParseObject(new ObjectBuilder(), node).Build());
                    }
                }
                else
                {
                    builder.Add(node.Name, node.InnerText);
                }
            }
            return builder;
        }

        int ParseArray(ObjectBuilder parent, XmlNode node)
        {
            int result = 0;
            ArrayBuilder builder = new ArrayBuilder();
            string name = node.Name;
            do
            {
                if (HasChild(node))
                {
                    builder.Add(ParseObject(new ObjectBuilder(), node).Build());
                }
                else
                {
                    builder.Add(node.InnerText);
                }
                node = node.NextSibling;
                ++result;
            }
            while (node != null && node.Name == name);
            parent.Add(name, builder.Build());
            return result;
        }

        bool HasChild(XmlNode node)
        {
            bool result = false;
            foreach (XmlNode child in node.ChildNodes)
            {
                if (child.NodeType != XmlNodeType.Text)
                {
                    result = true;
                    break;
                }
            }
            return result;
        }

        bool IsArray(XmlNode node)
        {
            bool result = false;
            if (node.NextSibling != null && node.NextSibling.Name == node.Name)
            {
                result = true;
            }
            return result;
        }
    }
}
